package com.microtf.inscription.framework.service.storage;

import com.microtf.inscription.framework.vo.storage.Config;
import com.microtf.inscription.framework.vo.storage.StorageObjectVo;
import com.qiniu.common.QiniuException;
import com.qiniu.http.Response;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.FetchRet;
import com.qiniu.storage.model.FileInfo;
import com.qiniu.util.Auth;
import com.qiniu.util.StringMap;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

/**
 * @author guliuzhong
 */
public class QiniuOssImpl implements Oss {
    Config config;

    public void setConfig(Config config) {
        this.config = config;
    }

    private Auth getAuth() {
        return Auth.create(config.getAccessKey(), config.getSecretKey());
    }

    private String getToken() {
        StringMap putPolicy = new StringMap();
        putPolicy.put("returnBody", "{\"key\":\"$(key)\",\"hash\":\"$(etag)\",\"bucket\":\"$(bucket)\",\"fsize\":$(fsize)}");
        return getAuth().uploadToken(config.getBucket(),null,3600,putPolicy);
    }

    @Override
    public StorageObjectVo put(byte[] data, String objName) throws StorageException {
        UploadManager uploadManager = new UploadManager(new Configuration());
        StorageObjectVo storageObject = new StorageObjectVo();
        try {
            Response r = uploadManager.put(data, objName, getToken());
            StringMap stringMap = r.jsonToMap();
            String key = (String) stringMap.get("key");
            storageObject.setObjectName(key);
            storageObject.setPrivateUrl(getPrivateUrl(key));
            storageObject.setUrl(getUrl(key));
        } catch (QiniuException e) {
            throw new StorageException(e.getMessage(), e.getCause());
        }
        return storageObject;
    }

    @Override
    public StorageObjectVo put(URL url, String objName) throws StorageException {
        BucketManager bucketManager = new BucketManager(getAuth(), new Configuration());

        StorageObjectVo storageObject = new StorageObjectVo();
        try {
            FetchRet fetch = bucketManager.fetch(url.toString(), config.getBucket(), objName);
            storageObject.setObjectName(fetch.key);
            storageObject.setPrivateUrl(getPrivateUrl(fetch.key));
            storageObject.setUrl(getUrl(fetch.key));
        } catch (QiniuException e) {
            throw new StorageException(e.getMessage(), e.getCause());
        }
        return storageObject;
    }

    @Override
    public StorageObjectVo put(InputStream inputStream, String objName) throws StorageException {
        UploadManager uploadManager = new UploadManager(new Configuration());
        StorageObjectVo storageObject = new StorageObjectVo();
        try {
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            byte[] bytes = new byte[1000];
            int readnum;
            do {
                readnum = inputStream.read(bytes, 0, 1000);
                if (readnum > 0) {
                    byteArrayOutputStream.write(bytes, 0, readnum);
                }
            } while (readnum > 0);
            Response r = uploadManager.put(byteArrayOutputStream.toByteArray(), objName, getToken());
            StringMap stringMap = r.jsonToMap();
            String key = (String) stringMap.get("key");
            storageObject.setObjectName(key);
            storageObject.setPrivateUrl(getPrivateUrl(key));
            storageObject.setUrl(getUrl(key));
        } catch (IOException e) {
            throw new StorageException(e.getMessage(), e.getCause());
        }
        return storageObject;
    }

    @Override
    public Boolean delete(String objName) throws StorageException {
        try {
            BucketManager bucketManager = new BucketManager(getAuth(), new Configuration());
            bucketManager.delete(config.getBucket(), objName);
        } catch (QiniuException e) {
            throw new StorageException(e.getMessage(), e.getCause());
        }
        return true;
    }
    @Override
    public String getUrl(String objName) {
        return String.format("%s%s", config.getRootPath(), objName);
    }
    @Override
    public String getPrivateUrl(String objName) {
        String url = String.format("%s%s", config.getRootPath(), objName);
        return getAuth().privateDownloadUrl(url,1000);
    }
    @Override
    public List<StorageObjectVo> getFileList(String prefix, int limit) {
        BucketManager bucketManager = new BucketManager(getAuth(), new Configuration());
        BucketManager.FileListIterator fileListIterator = bucketManager.createFileListIterator(config.getBucket(), prefix, limit, ":");
        List<StorageObjectVo> storageObjectVos = new ArrayList<>();
        while (fileListIterator.hasNext()){
            FileInfo[] items = fileListIterator.next();
            for (FileInfo item : items) {
                StorageObjectVo storageObjectVo = new StorageObjectVo();
                storageObjectVo.setObjectName(item.key);
                storageObjectVo.setUrl(getUrl(item.key));
                storageObjectVo.setPrivateUrl(getPrivateUrl(item.key));
                storageObjectVos.add(storageObjectVo);
            }
        }
        return storageObjectVos;
    }
}
